Skip to content

[JIRA DEVA11Y-128] Added permission to write to package directory for logging - #2

Merged
maunilm merged 1 commit into
mainfrom
DEVA11Y-128-1
Nov 21, 2025
Merged

[JIRA DEVA11Y-128] Added permission to write to package directory for logging#2
maunilm merged 1 commit into
mainfrom
DEVA11Y-128-1

Conversation

@Crash0v3rrid3

Copy link
Copy Markdown
Collaborator

No description provided.

@Crash0v3rrid3
Crash0v3rrid3 requested a review from a team as a code owner November 21, 2025 16:14
@maunilm
maunilm merged commit ca151ac into main Nov 21, 2025
2 checks passed
Crash0v3rrid3 added a commit that referenced this pull request Jul 30, 2026
…A11Y-483)

Addresses all code-review findings on the first cut:

- #1 Decide manifest ownership UNDER the lock from the live filesystem, not a
  startup PACKAGE_EXISTS snapshot. The lock is now taken unconditionally, so a
  peer that starts after the synthetic Package.swift already exists still
  serializes instead of running unprotected and getting its file deleted.
- #2 Reclaim a crashed peer's lock by PID liveness (kill -0), not a 5-min mtime
  that would steal a slow-but-alive long scan's lock.
- #3 Claim a stale lock atomically via rename so two waiters can't both reclaim.
- #4 Wait-timeout is non-fatal: it skips the scan (exit 0) with a visible
  'waiting...'/'skipping' notice instead of hanging a git commit then aborting it.
- #5 A non-EEXIST mkdir failure (unwritable/read-only/full TMPDIR) fails fast
  with an actionable message instead of waiting out the full timeout.
- #6 The lock lives under TMPDIR keyed by the package path, never inside the
  working tree, so a crash can't leave it to be git-added.
- #7 Consistent 'A11y scan:' message prefix.
- Also fixes a latent bug from the first cut: cleanup state (lock_dir/have_lock/
  created_package) is now global, since the EXIT trap fires after a11y_scan
  returns when its locals are out of scope (verified) -- previously the lock was
  never released on a normal run.

Verified with an integration test (staggered concurrent runs serialize; both
scans see Package.swift throughout; no tree/TMPDIR residue) and unit tests for
stale reclaim, live-owner detection, and fail-fast. Applied to bash/zsh/fish.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Crash0v3rrid3 added a commit that referenced this pull request Aug 3, 2026
…ft (DEVA11Y-483) (#33)

* fix(spm): serialize concurrent scans to protect synthetic Package.swift (DEVA11Y-483)

Guard the setup/scan/cleanup cycle with an atomic per-directory mkdir lock so
concurrent spm.sh invocations in the same working directory no longer race: the
first instance to exit can no longer delete the shared synthetic Package.swift
out from under a still-running peer. Stale locks left by killed peers are
reclaimed after 5 minutes; mkdir is used instead of flock(1) for macOS
portability. Applied to the bash, zsh and fish variants.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(spm): redesign concurrency lock to fully close the scan race (DEVA11Y-483)

Addresses all code-review findings on the first cut:

- #1 Decide manifest ownership UNDER the lock from the live filesystem, not a
  startup PACKAGE_EXISTS snapshot. The lock is now taken unconditionally, so a
  peer that starts after the synthetic Package.swift already exists still
  serializes instead of running unprotected and getting its file deleted.
- #2 Reclaim a crashed peer's lock by PID liveness (kill -0), not a 5-min mtime
  that would steal a slow-but-alive long scan's lock.
- #3 Claim a stale lock atomically via rename so two waiters can't both reclaim.
- #4 Wait-timeout is non-fatal: it skips the scan (exit 0) with a visible
  'waiting...'/'skipping' notice instead of hanging a git commit then aborting it.
- #5 A non-EEXIST mkdir failure (unwritable/read-only/full TMPDIR) fails fast
  with an actionable message instead of waiting out the full timeout.
- #6 The lock lives under TMPDIR keyed by the package path, never inside the
  working tree, so a crash can't leave it to be git-added.
- #7 Consistent 'A11y scan:' message prefix.
- Also fixes a latent bug from the first cut: cleanup state (lock_dir/have_lock/
  created_package) is now global, since the EXIT trap fires after a11y_scan
  returns when its locals are out of scope (verified) -- previously the lock was
  never released on a normal run.

Verified with an integration test (staggered concurrent runs serialize; both
scans see Package.swift throughout; no tree/TMPDIR residue) and unit tests for
stale reclaim, live-owner detection, and fail-fast. Applied to bash/zsh/fish.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): regenerate spm.sh checksum sidecars after lock redesign (DEVA11Y-483)

The concurrency-lock redesign edited all three spm.sh launchers but left their
.sha256 sidecars stale, which would make the self-update integrity check abort
on every run (dead on arrival, same class as the DEVA11Y-475 fix). Regenerate
all three sidecars to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Crash0v3rrid3 added a commit that referenced this pull request Aug 4, 2026
Addresses the two open code-review findings on the smoke workflow:

- Fidelity (#2): the e2e test asserted only that --non-strict exits 0, so a
  scan that authenticated but found nothing (silent no-op) would pass green.
  Now run the scan twice and use the tool's own exit-code contract: strict
  mode must exit non-zero, proving the intentional issues in SampleViews.swift
  were actually detected — not just that the plugin ran. Uses exit codes, not
  brittle output matching. Also drains output for diagnostics and treats an
  empty credential value as absent (skip) to match the workflow guard.

- Flakiness (#3): the scan hits BrowserStack (network + auth + CLI download)
  on every same-repo PR. Wrapped it in a bounded retry (3 attempts, 20s
  backoff) so a transient upstream hiccup doesn't red-block a PR; a consistent
  failure still fails the gate. swift test reuses the first build, so retries
  only re-run the scan.

Verified locally: tests compile; no-creds path still skips cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Crash0v3rrid3 added a commit that referenced this pull request Aug 6, 2026
* ci: add PR smoke-test workflow for the a11y-scan SPM plugin

Runs an end-to-end accessibility scan on every PR: builds the plugin and
executes a real scan against the tests/spm harness (sample SwiftUI sources
with intentional a11y issues), reusing the repo's own gated integration
test (testA11yScanPluginRuns) so the invocation stays in one place.

The scan downloads the BrowserStack CLI and makes authenticated calls, so
it is gated to same-repo PRs (secrets are never exposed to fork PRs) and
manual dispatch. Without the BROWSERSTACK_USERNAME / BROWSERSTACK_ACCESS_KEY
secrets configured the e2e test XCTSkips and the job still passes.

actions/checkout pinned by SHA to match existing workflows (DEVA11Y-476).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci: build/test tests/spm instead of plugin-only root

The repo root is a plugin-only package with no buildable target, so
`swift build` there fails ("does not contain a buildable target").
Building the tests/spm harness compiles the a11y-scan command plugin via
the path dependency plus the sample sources, so use that as the build step.

Verified locally on Swift 6.2: tests/spm `swift build` compiles the plugin,
and `swift test` passes with the e2e scan test skipping when RUN_A11Y_SCAN
is unset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(tests): use valid SwiftPM network-permission flag in scan scripts

run-a11y-scan.sh passed `--allow-network-connections 'all(ports: [])'` —
that is PackageDescription API syntax, not a valid CLI value, and the empty
port list did not satisfy the a11y-scan plugin's declared need for ports
80/443. SwiftPM therefore refused the scan:

  error: Plugin 'a11y-scan' wants permission to allow all network
  connections on ports: 80, 443. Use `--allow-network-connections
  all:80,443` to allow this.

Surfaced by the new PR smoke-test job, which is the first thing to run the
scan in CI. Fix per SwiftPM's own guidance: `all:80,443`. Applied to the
SwiftPM and Xcode harness scripts and the tests/spm README (same bug in all
three). Verified locally: the CLI now clears the permission gate and runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci: add scripts-lint job — bash -n on every launcher script

Adds a second, secret-free job that syntax-checks all six launcher scripts
under scripts/ (bash/zsh/fish x cli/spm) with `bash -n`. They are all bash
scripts (the zsh/fish variants only differ in which login shell they source
credentials from), so a single bash syntax gate covers them. Runs on all
PRs including forks; scripts are not executed (they self-update, register
git hooks and need credentials). Complements verify-selfupdate-checksums.yml,
which covers checksum integrity but not syntax.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): make no-secrets path truly skip, harden scripts-lint

Code-review follow-ups on the smoke workflow:

- Graceful degradation was only claimed, not real. GitHub exposes an unset
  secret as an empty string (present, not nil), and the reused test skips
  only on `env[...] != nil`, so a repo without the secrets would run the
  scan with empty creds and fail (script's `:?` under set -euo pipefail),
  not skip. Guard the scan step on the secrets being non-empty so it is
  skipped when absent and the job stays green on the build step. Fix the
  header comment to match.
- Correct the scripts-lint comment: the launchers' shebang is
  `#!/usr/bin/env bash -il`, not `#!/usr/bin/env bash`.
- Drop the fork-controllable filename from the `::notice/::error file=`
  workflow commands (workflow-command injection vector on fork PRs); log
  plain lines instead. bash -n still prints the real error location.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): assert scan detects issues + retry transient scan failures

Addresses the two open code-review findings on the smoke workflow:

- Fidelity (#2): the e2e test asserted only that --non-strict exits 0, so a
  scan that authenticated but found nothing (silent no-op) would pass green.
  Now run the scan twice and use the tool's own exit-code contract: strict
  mode must exit non-zero, proving the intentional issues in SampleViews.swift
  were actually detected — not just that the plugin ran. Uses exit codes, not
  brittle output matching. Also drains output for diagnostics and treats an
  empty credential value as absent (skip) to match the workflow guard.

- Flakiness (#3): the scan hits BrowserStack (network + auth + CLI download)
  on every same-repo PR. Wrapped it in a bounded retry (3 attempts, 20s
  backoff) so a transient upstream hiccup doesn't red-block a PR; a consistent
  failure still fails the gate. swift test reuses the first build, so retries
  only re-run the scan.

Verified locally: tests compile; no-creds path still skips cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants